package com.ruoyi.ade.tool;

import com.ruoyi.ade.llm.exception.AdeRecognizeException;
import com.ruoyi.ade.llm.model.Ade;

import java.util.ArrayList;
import java.util.List;

public class AdeCompareUtils {

    public static final String LEVEL_L1 = "L1";   //ADE识别准确  实体提取也准确
    public static final String LEVEL_L2 = "L2";   //ADE识别准确  实体提取有差异
    public static final String LEVEL_L3 = "L3";   //ADE识别有差异，但是有交集
    public static final String LEVEL_LN = "LN";   //ADE识别不同  识别错误


    //两个   ADE对别结果
    public static final String ADE_SAME = "ADE_SAME";   //完全相同
    public static final String ADE_NEAR = "ADE_NEAR";   //ADE识别相同  实体有差异
    public static final String ADE_DIFF = "ADE_DIFF";   //ADE完全不同

    public static String compare(List<Ade> references, List<Ade> ades){
        if(references== null || ades == null) throw new AdeRecognizeException("references and ades can not be null!");

        //如果参考集合是空
        if (references.size() == 0) {
            //如果答案集合是空
            if(ades.size() == 0) return LEVEL_L1;
            else  return LEVEL_LN;
        }else{ //如果参考集合不为空
            //如果答案集合是空
            if(ades.size() == 0) return LEVEL_LN;

            int countSame = 0;
            int countNear = 0;
            for (Ade reference : references) {
                for(Ade ade : ades){
                    String com = compare(reference, ade);
                    if(com.equals(ADE_SAME)){
                        countSame++;
                        break;
                    }else if(com.equals(ADE_NEAR)){
                        countNear++;
                        break;
                    }
                }
            }
            //ADE 完全相同
            if(countSame == references.size() && countSame == ades.size()) return LEVEL_L1;
            //ADE 识别相同
            if((countSame+countNear)== references.size() && (countSame+countNear)== ades.size()) return LEVEL_L2;
            //ADE 有差异
            if(countSame == 0 && countNear == 0) return LEVEL_LN;
            return LEVEL_L3;
        }
    }

    /**
     *
     * @param reference
     * @param ade
     * @return      ADE_SAME ADE_NEAR ADE_DIFF
     */
    public static String compare(Ade reference, Ade ade){
        if(checkOverlap(ade.getSentence(),reference.getSentence())){  //如果识别的ADE一致
            if(ade.getDrugs().size() == reference.getDrugs().size()){
                int count = 0;
                for (String drug : ade.getDrugs()) {
                    for (String referenceDrug : reference.getDrugs()) {
                        if(checkOverlap(drug,referenceDrug)){
                            count++;
                            break;
                        }
                    }
                }
                if(count == ade.getDrugs().size()){ //如果drugs实体一致  继续分析不良反应实体
                    if(ade.getReactions().size() == reference.getReactions().size()){
                        int count2 = 0;
                        for (String reaction : ade.getReactions()) {
                            for (String referenceReaction : reference.getReactions()) {
                                if(checkOverlap(reaction,referenceReaction)){
                                    count2++;
                                    break;
                                }
                            }
                        }
                        if(count2 == ade.getReactions().size()){
                            return ADE_SAME;
                        }else
                            return ADE_NEAR;
                    }else{
                         return ADE_NEAR;
                    }
                }else{
                    return ADE_NEAR;
                }
            }else{
                return ADE_NEAR;
            }
        }else{
            return ADE_DIFF;
        }
    }

    public static void main(String[] args) {
//        List<Ade> references = new ArrayList<>();
//        List<Ade> ades = new ArrayList<>();
//        Ade reference = new Ade();
//        reference.setSentence("患者出现皮肤过敏");
//        reference.setDrugs(new ArrayList<>());
//        reference.setReactions(new ArrayList<>());
//        reference.getReactions().add("皮肤过敏");
//
//        Ade ade = new Ade();
//        ade.setSentence("患者出现皮肤,过敏,继续观察");
//        ade.setDrugs(new ArrayList<>());
//        ade.setReactions(new ArrayList<>());
//        ade.getReactions().add("皮肤过敏了吧");
//        ade.getReactions().add("头痛");
//
//        Ade ade2 = new Ade();
//        ade2.setSentence("药物性肝炎");
//        ade2.setDrugs(new ArrayList<>());
//        ade2.setReactions(new ArrayList<>());
//        ade2.getReactions().add("药物性肝炎");
//        ade2.getReactions().add("头痛");

//        references.add(reference);
//        ades.add(ade);
//        ades.add(ade2);

//        System.out.println(compare(references, ades));
        System.out.println(checkOverlap("体温异常", "体温升高"));
    }

    public static boolean checkOverlap(String str1, String str2) {
        // 确定较短的字符串和较长的字符串
        String shorter = str1.length() <= str2.length() ? str1 : str2;
        String longer = str1.length() <= str2.length() ? str2 : str1;

        // 计算最短交叠长度：短字符串长度的50%以上
        int minOverlapLength = (int) Math.ceil(shorter.length() * 0.5);

        // 检查shorter是否是longer的子串
        if (longer.contains(shorter)) {
            return true;
        }

        // 检查shorter的前缀是否与longer的后缀交叠
        for (int i = minOverlapLength; i <= shorter.length(); i++) {
            String prefix = shorter.substring(0, i);
            if (longer.endsWith(prefix)) {
                return true;
            }
        }

        // 检查shorter的后缀是否与longer的前缀交叠
        for (int i = minOverlapLength; i <= shorter.length(); i++) {
            String suffix = shorter.substring(shorter.length() - i);
            if (longer.startsWith(suffix)) {
                return true;
            }
        }

        if(similarity(str1,str2)>0.5) return true;
        int[] nSizes = {3, 4, 5};
        if(JaccardStringSimilarity.enhancedJaccardSimilarity(str1,str2,nSizes)>0.3) return true;

        return false;
    }




    // 计算编辑距离（Levenshtein Distance）
    public static int levenshteinDistance(String s1, String s2) {
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];

        for (int i = 0; i <= s1.length(); i++) {
            for (int j = 0; j <= s2.length(); j++) {
                if (i == 0) {
                    dp[i][j] = j;
                } else if (j == 0) {
                    dp[i][j] = i;
                } else {
                    dp[i][j] = Math.min(
                            Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1),
                            dp[i - 1][j - 1] + (s1.charAt(i - 1) == s2.charAt(j - 1) ? 0 : 1)
                    );
                }
            }
        }

        return dp[s1.length()][s2.length()];
    }

    // 计算相似度（0.0到1.0之间的值，值越大表示越相似）
    public static double similarity(String s1, String s2) {
        if (s1 == null || s2 == null) {
            return 0.0;
        }

        int distance = levenshteinDistance(s1, s2);
        int maxLength = Math.max(s1.length(), s2.length());

        return 1.0 - (double) distance / maxLength;
    }




}
